package
{
import flash.display.MovieClip;
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.media.Video;
import flash.media.Camera;
import flash.media.Microphone;
import flash.external.ExternalInterface;
import flash.system.Security;
import flash.events.NetStatusEvent;
import flash.utils.setInterval;
import flash.utils.clearInterval;
import flash.events.StatusEvent;
import flash.media.H264VideoStreamSettings;
import flash.media.H264Profile;

public class RtmpStreamer extends MovieClip
{

  internal var nc:NetConnection;
  internal var ns:NetStream;
  internal var nsPlayer:NetStream;
  internal var vidPlayer:Video;
  internal var cam:Camera;
  internal var mic:Microphone;
  internal var _camWidth:int = 640;
  internal var _camHeight:int = 480;
  internal var _camFps:int = 15;
  internal var _camFrameInterval:int = 25;
  internal var _camBandwidth:int = 200000;
  internal var _camQuality:int = 90;
  internal var _micQuality:int = 10;
  internal var _micRate:int = 44;
  internal var _micSilent:int = 0;
  internal var _screenWidth:int = 640;
  internal var _screenHeight:int = 480;
  internal var _screenX:int = 0;
  internal var _screenY:int = 0;
  internal var _hw_error_camera_not_install:int = -1;
  internal var _hw_error_camera_took_busy:int = -2;
  internal var _hw_error_camera_muted:int = -3;
  internal var _hw_error_microphone_not_install:int = -11;
  internal var _hw_error_microphone_muted:int = -12;
  internal var _checkCamTimes:int = 0;
  internal var _intervalId:int = 0;

  public function RtmpStreamer()
  {
    ExternalInterface.addCallback("setCamMicInfo", this.setCamMicInfo);
    ExternalInterface.addCallback("publish", this.publish);
    ExternalInterface.addCallback("disconnect", this.disconnect);
    Security.allowDomain("*");
    Security.allowInsecureDomain("*");
  }

  public function setCamMicInfo(_arg_1:int, _arg_2:int, _arg_3:int, _arg_4:int):void
  {
    if (((((((((((_arg_1 < 50) || (_arg_1 > 0x0500)) || (!((_arg_1 % 4) == 0))) || (_arg_2 < 50)) || (_arg_2 > 720)) || (!((_arg_2 % 4) == 0))) || (_arg_3 < 5)) || (_arg_3 > 60)) || (_arg_4 < (100 * 125))) || (_arg_4 > (1500 * 125))))
    {
      ExternalInterface.call("console.log", "error, limit w[50,1280] h[50,720], framerate[5,60], rate[100,1500kbps]");
      return;
    };
    this.setScreenSize(_arg_1, _arg_2);
    this.setCamMode(_arg_1, _arg_2, _arg_3);
    this.setCamQuality(_arg_4, 90);
  }

  public function setScreenSize(_arg_1:int, _arg_2:int):void
  {
    this._screenWidth = _arg_1;
    this._screenHeight = _arg_2;
  }

  public function setScreenPosition(_arg_1:int, _arg_2:int):void
  {
    this._screenX = _arg_1;
    this._screenY = _arg_2;
  }

  public function setCamMode(_arg_1:int, _arg_2:int, _arg_3:int):void
  {
    this._camWidth = _arg_1;
    this._camHeight = _arg_2;
    this._camFps = _arg_3;
  }

  public function setCamFrameInterval(_arg_1:int):void
  {
    this._camFrameInterval = _arg_1;
  }

  public function setCamQuality(_arg_1:int, _arg_2:int):void
  {
    this._camBandwidth = _arg_1;
    this._camQuality = _arg_2;
  }

  public function setMicQuality(_arg_1:int):void
  {
    this._micQuality = _arg_1;
  }

  public function setMicRate(_arg_1:int):void
  {
    this._micRate = _arg_1;
  }

  public function setMicSilent(_arg_1:int):void
  {
    this._micSilent = _arg_1;
  }

  public function publish(url:String, name:String):void
  {
    if (url.indexOf("rtmp://") != 0)
    {
      ExternalInterface.call("console.log", ("invalid url protocol, should be rtmp://, url:" + url));
      return;
    };
    this.connect(url, name, function (_arg_1:String):void
    {
      publishCamera(_arg_1);
      displayPublishingVideo();
    });
  }

  public function disconnect():void
  {
    this.nc.close();
    this.ns.attachCamera(null);
    this.ns.attachAudio(null);
    this.ns.close();
    if (this.vidPlayer)
    {
      this.vidPlayer.clear();
      removeChild(this.vidPlayer);
    };
  }

  private function connect(url:String, name:String, callback:Function):void
  {
    this.nc = new NetConnection();
    this.nc.addEventListener(NetStatusEvent.NET_STATUS, function (_arg_1:NetStatusEvent):void
    {
      ExternalInterface.call("console.log", ("try to connect to " + url));
      if (_arg_1.info.code == "NetConnection.Connect.Success")
      {
        callback(name);
      };
      ExternalInterface.call("console.log", ("swf event code:" + _arg_1.info.code));
    });
    this.nc.connect(url);
  }

  public function isCameraBusy():void
  {
    this._intervalId = setInterval(this.cameraStatusCheckInterval, 50);
  }

  public function swfHardwareStatusCallback(_arg_1:int):void
  {
    ExternalInterface.call("console.log", ("hw info code:" + _arg_1));
  }

  public function cameraStatusCheckInterval():void
  {
    if (this.cam.currentFPS > 0)
    {
      clearInterval(this._intervalId);
    }
    else
    {
      this._checkCamTimes++;
      if (this._checkCamTimes > 30)
      {
        clearInterval(this._intervalId);
        this.swfHardwareStatusCallback(this._hw_error_camera_took_busy);
        this._checkCamTimes = 0;
      };
    };
  }

  public function camStatusHandler(_arg_1:StatusEvent):void
  {
    if (this.cam.muted)
    {
      this.swfHardwareStatusCallback(this._hw_error_camera_muted);
    };
    this.cam.removeEventListener(StatusEvent.STATUS, this.camStatusHandler);
  }

  public function micStatusHandler(_arg_1:StatusEvent):void
  {
    if (this.mic.muted)
    {
      this.swfHardwareStatusCallback(this._hw_error_microphone_muted);
    };
    this.mic.removeEventListener(StatusEvent.STATUS, this.micStatusHandler);
  }

  private function publishCamera(_arg_1:String):void
  {
    this.cam = Camera.getCamera();
    if (this.cam == null)
    {
      if (Camera.names.length <= 0)
      {
        this.swfHardwareStatusCallback(this._hw_error_camera_not_install);
      };
      ExternalInterface.call("console.log", "cam is null");
    };
    this.cam.setMode(this._camWidth, this._camHeight, this._camFps);
    this.cam.setKeyFrameInterval(this._camFrameInterval);
    this.cam.setQuality(this._camBandwidth, this._camQuality);
    var _local_2:H264VideoStreamSettings = new H264VideoStreamSettings();
    _local_2.setProfileLevel(H264Profile.MAIN, "4");
    this.mic = Microphone.getMicrophone();
    if (this.mic == null)
    {
      if (Microphone.names.length <= 0)
      {
        this.swfHardwareStatusCallback(this._hw_error_microphone_not_install);
      };
    };
    this.mic.encodeQuality = this._micQuality;
    this.mic.rate = this._micRate;
    this.mic.setSilenceLevel(this._micSilent, 5);
    this.ns = new NetStream(this.nc);
    this.ns.videoStreamSettings = _local_2;
    this.ns.attachCamera(this.cam);
    this.ns.attachAudio(this.mic);
    this.ns.publish(_arg_1, "live");
    this.isCameraBusy();
    this.cam.addEventListener(StatusEvent.STATUS, this.camStatusHandler);
    this.mic.addEventListener(StatusEvent.STATUS, this.micStatusHandler);
  }

  private function displayPublishingVideo():void
  {
    this.vidPlayer = this.getPlayer();
    this.vidPlayer.attachCamera(this.cam);
    addChild(this.vidPlayer);
  }

  private function getPlayer():Video
  {
    this.vidPlayer = new Video(this._screenWidth, this._screenHeight);
    this.vidPlayer.x = this._screenX;
    this.vidPlayer.y = this._screenY;
    return (this.vidPlayer);
  }


}
}//package
